
local EventProtocol = class("EventProtocol")

function EventProtocol:ctor()
    self.listeners_ = {}
    self.nextListenerHandleIndex_ = 0
    self.target_ = self
    self.removeTempListerner = {}
end

function EventProtocol:addEventListener(eventName, listener, tag)
	assert(type(eventName) == "string" and eventName ~= "","EventProtocol:addEventListener() - invalid eventName")

    if self.listeners_[eventName] == nil then
        self.listeners_[eventName] = {}
    end

    self.nextListenerHandleIndex_ = self.nextListenerHandleIndex_ + 1
    local handle = tostring(self.nextListenerHandleIndex_)
    tag = tag or ""
    self.listeners_[eventName][handle] = {listener, tag}

    return handle
end

function EventProtocol:dispatchEvent(event)
    local eventName = event.name

    if self.listeners_[eventName] == nil then return end
    event.target = self.target_
    event.stop_ = false
    event.stop = function(self)
        self.stop_ = true
    end

    --执行副本 避免事件分发中增加事件导致其他事件未执行
    local tempListeners = {}
    for handle, listener in pairs(self.listeners_[eventName]) do
        tempListeners[handle] = listener
    end
    self.removeTempListerner = {} --handle的是唯一的 可以直接根据这个来判断

    for handle, listener in pairs(tempListeners) do
        if self.listeners_[eventName] == nil then return end

        if not self.removeTempListerner[handle] then
            event.tag = listener[2]
            -- print(eventName)
            listener[1](event)
            if event.stop_ then
                break
            end
        end
    end

    return self.target_
end

function EventProtocol:removeEventListener(handleToRemove)
    for eventName, listenersForEvent in pairs(self.listeners_) do
        for handle, _ in pairs(listenersForEvent) do
            if handle == handleToRemove then
                listenersForEvent[handle] = nil
                self.removeTempListerner[handle] = true
                return self.target_
            end
        end
    end

    return self.target_
end

function EventProtocol:removeEventListenersByTag(tagToRemove)
    for eventName, listenersForEvent in pairs(self.listeners_) do
        for handle, listener in pairs(listenersForEvent) do
            if listener[2] == tagToRemove then
                listenersForEvent[handle] = nil
                self.removeTempListerner[handle] = true
            end
        end
    end

    return self.target_
end

function EventProtocol:removeEventListenersByEvent(eventName)
    self.listeners_[eventName] = nil
    return self.target_
end

function EventProtocol:removeAllEventListeners()
    self.listeners_ = {}
    return self.target_
end

function EventProtocol:hasEventListener(eventName)
    local t = self.listeners_[eventName]
    if not t then
        return false
    end
    for _, __ in pairs(t) do
        return true
    end
    return false
end

function EventProtocol:dumpAllEventListeners()
    print("---- EventProtocol:dumpAllEventListeners() ----")
    for name, listeners in pairs(self.listeners_) do
        printf("-- event: %s", name)
        for handle, listener in pairs(listeners) do
            printf("--     listener: %s, handle: %s", tostring(listener[1]), tostring(handle))
        end
    end
    return self.target_
end

return EventProtocol
